home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / AUTOSRV.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  20KB  |  625 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.15  $
  6. //
  7. // OLE Automation Server Implementation: TServedObject
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_APPDESC_H)
  11. # include <ocf/appdesc.h>
  12. #endif
  13. #if !defined(OCF_OCREG_H)
  14. # include <ocf/ocreg.h>
  15. #endif
  16. #if !defined(OCF_OCCTRL_H) && defined(BI_PLAT_WIN32)
  17. # include <ocf/occtrl.h>
  18. #endif
  19.  
  20. //----------------------------------------------------------------------------
  21. // TServedObject implementation
  22. //
  23.  
  24. TServedObjectCreator::TServedObjectCreator(TAppDescriptor& appDesc)
  25. :
  26.   AppDesc(appDesc),
  27.   AppObject(0)
  28. {
  29. }
  30.  
  31. TUnknown*
  32. TServedObjectCreator::CreateObject(TObjectDescriptor objDesc,
  33.                                    IUnknown* outer)
  34. {
  35.   TServedObject* ifc = AppDesc.FindServed(objDesc);
  36.   if (!ifc)
  37.     ifc = new TServedObject(objDesc, *this, outer);
  38.   if (!AppObject)
  39.     AppObject = ifc;
  40.   return ifc;
  41. }
  42.  
  43. IDispatch*
  44. TServedObjectCreator::CreateDispatch(TObjectDescriptor objDesc, IUnknown* outer)
  45. {
  46.   TServedObject* obj = AppDesc.FindServed(objDesc);
  47.   if (!obj)
  48.     obj = new TServedObject(objDesc, *this, outer);
  49.   if (!AppObject)
  50.     AppObject = obj;
  51.   return *obj;
  52. }
  53.  
  54. void
  55. TServedObjectCreator::Attach(TServedObject& obj)
  56. {
  57.   AppDesc.AddServed(obj);
  58.   ++ObjCount;
  59. }
  60.  
  61. void
  62. TServedObjectCreator::Detach(TServedObject& obj)
  63. {
  64.   AppDesc.RemoveServed(obj);
  65.   if (--ObjCount == 0)
  66.     delete this;
  67. }
  68.  
  69. #if defined(BI_NAMESPACE)
  70. namespace OCF {
  71. #endif
  72.  
  73. const GUID __cdecl _OCFDATA IID_TServedObject = {0x02A101L,0,0,{0xC0,0,0,0,0,0,0,0x46}};
  74.  
  75. #if defined(BI_NAMESPACE)
  76. } // namespace OCF
  77. #endif
  78.  
  79. DEFINE_QI_OLEBASE(IDispatch,      0x20400L)
  80. DEFINE_QI_OLEBASE(ITypeInfo,      0x20401L)
  81.  
  82. DEFINE_COMBASES2(TServedCOM, IDispatch, ITypeInfo)
  83.  
  84. HRESULT TServedObject::QueryObject(const GUID far& iid, void far* far* pif)
  85. {
  86.   GUID qid = iid;
  87.  
  88.   if (iid == IID_TServedObject) {
  89.     *pif = this;       // return actual pointer to this object
  90.     return HR_NOERROR; // non-interface returned, no AddRef(), do not Release
  91.   }
  92.   if ((iidEvent != IID_NULL) && (iid == iidEvent))
  93.     qid = IID_IDispatch;
  94.   return TServedCOM::QueryObject (qid, pif);  // query inherited bases
  95. }
  96.  
  97. TServedObject::TServedObject(TObjectDescriptor& objDesc,
  98.                              TServedObjectCreator& creator,
  99.                              IUnknown* outer)
  100. :
  101.   Object(const_cast<void*>(objDesc.Object)), Destruct(objDesc.Destruct),
  102.   Creator(creator), Class(objDesc.Class), iidEvent(IID_NULL)
  103. {
  104.   SetOuter(outer ? outer
  105.        : &objDesc.Class->Aggregate(const_cast<void*>(objDesc.Object), *this));
  106.   ReqLang = creator.AppDesc.GetAppLang();  // do we really need to initialize here?
  107.   creator.Attach(*this);
  108.   RootObject = objDesc.MostDerived();
  109. } // note: RefCnt = 0 on creation, will ++ in TAutoVal operator(IDispatch*)
  110.  
  111. TServedObject::~TServedObject()
  112. {
  113.   if (Object && Destruct != TObjectDescriptor::Quiet) {
  114.     TAutoCommand* cmdobj;
  115.     try {
  116.       cmdobj = Class->GetDestructor()(Object, Destruct);
  117.       cmdobj->Invoke();
  118.     }
  119.     catch(TXAuto&) {
  120.       // we can't indicate any error here
  121.     }
  122.     delete cmdobj;
  123.   }
  124.   Creator.Detach(*this);
  125. }
  126.  
  127. //
  128. // IDispatch implementation
  129. //
  130.  
  131. HRESULT _IFUNC
  132. TServedObject::GetTypeInfoCount(unsigned int far* pctinfo)
  133. {
  134.   *pctinfo = 1;
  135.   return HR_NOERROR;
  136. }
  137.  
  138. HRESULT _IFUNC
  139. TServedObject::GetTypeInfo(unsigned int /*itinfo*/, LCID lcid,
  140.                            ITypeInfo* far* pptinfo)
  141. {
  142.   ReqLang = LANGIDFROMLCID(lcid);
  143.   *pptinfo = static_cast<ITypeInfo*>(this);
  144.   AddRef();
  145.   return HR_NOERROR;
  146. }
  147.  
  148. HRESULT _IFUNC
  149. TServedObject::GetIDsOfNames(const IID far& riid, OLECHAR far* far* names,
  150.                           unsigned int cNames, LCID lcid, DISPID far* dispIds)
  151. {
  152.   if (riid != IID_NULL)
  153.     return HR_DISP_UNKNOWNINTERFACE;
  154.  
  155.   HRESULT retval = HR_NOERROR;
  156.   TAutoSymbol* symbol;
  157.   for (int i = 0; i < cNames; i++) {
  158.     dispIds[i] = -1;
  159.     if (i == 0) {
  160.       symbol = Class->Lookup(OleStr(names[0]), LANGIDFROMLCID(lcid),
  161.                              asAnyCommand, dispIds[0]);
  162.       if (!symbol)
  163.         retval = HR_DISP_UNKNOWNNAME;
  164.     }
  165.     else if (symbol) {
  166.       if (!Class->LookupArg(OleStr(names[i]), LANGIDFROMLCID(lcid), symbol, dispIds[i]))
  167.         retval = HR_DISP_UNKNOWNNAME;
  168.     }
  169.   }
  170.   return retval;
  171. }
  172.  
  173. //
  174. //
  175. //
  176. HRESULT _IFUNC
  177. TServedObject::Invoke(DISPID dispidMember, const IID far& /*riid*/, LCID lcid,
  178.                       unsigned short wFlags, DISPPARAMS far* dispparams,
  179.                       VARIANT far* varResult, EXCEPINFO far* exceptInfo,
  180.                       unsigned int far* retArgErr)
  181. {
  182.   // Make a copy of the object in case there's this pointer adjustment
  183.   //
  184.   ObjectPtr object = Object;
  185.  
  186.   // Make sure our object is still valid
  187.   //
  188.   if (!object) {
  189.     return HR_DISP_MEMBERNOTFOUND;
  190.   }
  191.  
  192.   // Build an object representing the data passed in
  193.   //
  194.   TAutoStack stack(dispidMember, dispparams->rgvarg, lcid, dispparams->cArgs,
  195.                    dispparams->cNamedArgs, dispparams->rgdispidNamedArgs,
  196.                    this);
  197.  
  198.   // Find the symbol we're asked to dispatch to
  199.   //
  200.   stack.Symbol = Class->FindId(dispidMember, object);
  201.  
  202.   if (!stack.Symbol) {
  203. #if defined(BI_PLAT_WIN32)
  204.     // NOTE: This is a 'hack' that allows TServedObject to expose a generic method
  205.     //       that's used for cases when the object does not provide a method
  206.     //       that matches the dispId invoked.
  207.     //       It is used by our container support for sinking non-standard events.
  208.     //
  209.     if ((stack.Symbol = Class->FindId(DISPID_CATCH_ALL, object)) == NULL)
  210. #endif
  211.       return HR_DISP_MEMBERNOTFOUND;
  212.   }
  213.  
  214.   // Check the attribute bits to ensure we support the type
  215.   //
  216.   if (!stack.Symbol->TestFlag(wFlags)) {
  217.     return HR_DISP_MEMBERNOTFOUND;
  218.   }
  219.  
  220.   // Check if we need return result
  221.   // NOTE: Some servers [such as Word.Basic] seem to be very picky about
  222.   //       the distinction between a function and procedure. They are not
  223.   //       as flexible as we are here..
  224.   //
  225.   if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
  226.     varResult = 0;
  227.  
  228.  
  229.   // Check that the number of arguments sent matches what we're expecting
  230.   //
  231. #if defined(BI_PLAT_WIN16)
  232.   if ((stack.ArgSymbolCount = Class->GetArgCount(*stack.Symbol)) +
  233.       ((wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF)) != 0) < stack.ArgCount)
  234.     return HR_DISP_BADPARAMCOUNT;
  235.  
  236. #elif defined(BI_PLAT_WIN32)
  237.   // Again here we'll have to relax a little on the param count check since in the
  238.   // case of the DISPID_CATCH_ALL, the handler is a generic one that can handle
  239.   // any number of parameters.
  240.   //
  241.   if (((stack.ArgSymbolCount = Class->GetArgCount(*stack.Symbol)) +
  242.       ((wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF)) != 0) < stack.ArgCount) &&
  243.         (stack.Symbol->DispId != DISPID_CATCH_ALL))
  244.     return HR_DISP_BADPARAMCOUNT;
  245.  
  246. #endif
  247.  
  248.   // Dispatch via the command object and hope we're OK
  249.   //
  250.   switch(Class->Dispatch(object, Creator, *this, wFlags, stack, (TAutoVal*)varResult)) {
  251.     case TXAuto::xNoError:
  252.           return HR_NOERROR;
  253.  
  254.     case TXAuto::xNotIDispatch:
  255.     case TXAuto::xForeignIDispatch:
  256.           return HR_DISP_BADVARTYPE;
  257.  
  258.     case TXAuto::xValidateFailure:
  259.          *retArgErr = stack.CurrentArg;
  260.           return HR_DISP_OVERFLOW;
  261.  
  262.     case TXAuto::xConversionFailure:
  263.     case TXAuto::xTypeMismatch:
  264.          *retArgErr = stack.CurrentArg;
  265.           return HR_DISP_TYPEMISMATCH;
  266.  
  267.     case TXAuto::xNoArgSymbol:
  268.          *retArgErr = stack.CurrentArg;
  269.           return HR_DISP_PARAMNOTFOUND;
  270.  
  271.     case TXAuto::xParameterMissing:
  272.     case TXAuto::xNoDefaultValue:
  273.           return HR_DISP_PARAMNOTOPTIONAL;
  274.  
  275.     case TXAuto::xErrorStatus:
  276.       if (exceptInfo) {
  277.         exceptInfo->wCode = (unsigned short)stack.ErrorCode;
  278.         exceptInfo->wReserved = 0;
  279.         exceptInfo->bstrSource = NS_CLASSLIB::SysAllocString(
  280.           Creator.AppDesc.GetAppName(LANGIDFROMLCID(lcid)));
  281.         exceptInfo->bstrDescription = NS_CLASSLIB::SysAllocString(
  282.           stack.ErrorMsg);
  283.         exceptInfo->bstrHelpFile = 0;
  284.         exceptInfo->pfnDeferredFillIn = 0;
  285.  
  286.         // INVESTIGATE: Is there a method to relay better SCODEs ?
  287.         //
  288.         exceptInfo->scode = E_FAIL;
  289.       }
  290.       return HR_DISP_EXCEPTION;
  291.  
  292.   case TXAuto::xExecutionFailure:
  293.   default:
  294.         // INVESTIGATE: Is there a better error code here ?
  295.         //
  296.         return HR_DISP_OVERFLOW;
  297.   }
  298. }
  299.  
  300.  
  301. //----------------------------------------------------------------------------
  302. // ITypeInfo implementation
  303. //
  304.  
  305. HRESULT _IFUNC
  306. TServedObject::GetTypeAttr(TYPEATTR far* far* retTypeAttr)
  307. {
  308.   Class->CountCommands();    // force update of symbol counts;
  309.   TYPEATTR* ta = (TYPEATTR*)new char[sizeof(TYPEATTR)];
  310.   memset(ta, 0, sizeof(TYPEATTR));
  311.   Creator.AppDesc.GetClassId(Class, ta->guid);
  312.   ta->lcid = ReqLang;
  313.   ta->typekind = TKIND_DISPATCH;
  314.   ta->wTypeFlags = Class->GetTypeFlags();
  315.   ta->cFuncs = Class->FunctionCount;
  316.   ta->cVars  = Class->VariableCount;
  317.   ta->wMajorVerNum = Creator.AppDesc.GetVersionField(0);
  318.   ta->wMinorVerNum = Creator.AppDesc.GetVersionField(1);
  319.   *retTypeAttr = ta;
  320.   return HR_NOERROR;
  321. }
  322.  
  323. void _IFUNC
  324. TServedObject::ReleaseTypeAttr(TYPEATTR far* ptypeattr)
  325. {
  326.   delete [] (char*)ptypeattr;
  327. }
  328.  
  329. HRESULT _IFUNC
  330. TServedObject::GetFuncDesc(unsigned int index, FUNCDESC far* far* retDesc)
  331. {
  332.   MEMBERID cmdId = 0;   // must initialize, FindFunction recursively adjusts it
  333.   TAutoSymbol* sym = Class->FindFunction(index, cmdId);
  334.   if (!sym || !retDesc)
  335.     return HR_INVALIDARG;
  336.   int kind = (sym->GetFlags() & asOleType);
  337.   bool isPropSet = kind==INVOKE_PROPERTYPUT || kind==INVOKE_PROPERTYPUTREF;
  338.   int argCount = Class->GetArgCount(*sym);
  339.   int asize = sizeof(ELEMDESC) * (argCount+isPropSet) + sizeof(FUNCDESC);
  340.   int size = (argCount+1) * sizeof(TYPEDESC) + asize;
  341.   FUNCDESC* fd = (FUNCDESC*)new char[size];
  342.   TYPEDESC* ptrtd = (TYPEDESC*)((char*)fd + asize); // for indirected types
  343.   memset(fd, 0, size);
  344.   fd->cParams = short(argCount + isPropSet);
  345.   fd->lprgelemdescParam = (ELEMDESC*)(fd+1);
  346.   fd->memid = cmdId;
  347.   fd->funckind = FUNC_DISPATCH;
  348.   fd->invkind = (INVOKEKIND)kind;
  349.   fd->callconv = CC_CDECL;  // need to set to prevent typelib.dll asserts
  350.   fd->cScodes = -1;
  351.   ELEMDESC* argDesc = &fd->elemdescFunc;
  352.   if (isPropSet){
  353.     argDesc->tdesc.vt = VT_EMPTY;
  354.     argDesc = (ELEMDESC*)(fd+1);
  355.   }
  356.   for (int argIndex = 0; argIndex <= argCount; argIndex++, sym++, ptrtd++) {
  357.     TAutoClass* cls = sym->GetClass();
  358.     if (cls) {
  359.       argDesc->tdesc.vt = VT_USERDEFINED;
  360.       argDesc->tdesc.hreftype = (HREFTYPE)cls;
  361.     } else if (sym->IsEnum()) {
  362.       argDesc->tdesc.vt = atString;  // expose enumerated type as string
  363.     } else if (sym->IsArray()) {
  364.       argDesc->tdesc.vt = VT_SAFEARRAY;
  365.       argDesc->tdesc.lptdesc = ptrtd;
  366.       ptrtd->vt = sym->GetDataType();
  367.     } else if (sym->IsByRef()) {
  368.       argDesc->tdesc.vt = VT_PTR;
  369.       argDesc->tdesc.lptdesc = ptrtd;
  370.       ptrtd->vt = sym->GetDataType();
  371.     } else {
  372.       argDesc->tdesc.vt = sym->GetDataType();
  373.     }
  374.     argDesc++;
  375.     if (argIndex == 0) {
  376.       if (!isPropSet)
  377.         argDesc = (ELEMDESC*)(fd+1);
  378.     } else {
  379.       if (sym->Doc)    // argument optional if has default string
  380.         fd->cParamsOpt++;
  381.     }
  382.   }
  383.   *retDesc = fd;
  384.   return HR_NOERROR;
  385. }
  386.  
  387. void _IFUNC
  388. TServedObject::ReleaseFuncDesc(FUNCDESC far* pfuncdesc)
  389. {
  390.   delete [] (char*)pfuncdesc;
  391. }
  392.  
  393. HRESULT _IFUNC
  394. TServedObject::GetVarDesc(unsigned int index, VARDESC far* far* retDesc)
  395. {
  396.   VARDESC* vd = (VARDESC*)new char[sizeof(VARDESC) + sizeof(TYPEDESC)];
  397.   TYPEDESC* ptrtd = (TYPEDESC*)((char*)vd + sizeof(VARDESC));
  398.   memset(vd, 0, sizeof(VARDESC)+sizeof(TYPEDESC));
  399.   MEMBERID cmdId = 0;   // must initialize, FindVariable recursively adjusts it
  400.   TAutoSymbol* sym = Class->FindVariable(index, cmdId);
  401.   if (!sym || !retDesc)
  402.     return HR_INVALIDARG;
  403.   TAutoClass* cls = sym->GetClass();
  404.   vd->memid = cmdId;
  405.   vd->varkind = VAR_DISPATCH;
  406.   if (cls) {
  407.     vd->elemdescVar.tdesc.vt = VT_USERDEFINED;
  408.     vd->elemdescVar.tdesc.hreftype = (HREFTYPE)cls;
  409.   } else if (sym->IsEnum()) {
  410.       vd->elemdescVar.tdesc.vt = atString;  // expose enumerated type as string
  411.   } else if (sym->IsArray()) {
  412.     vd->elemdescVar.tdesc.vt = VT_SAFEARRAY;
  413.     vd->elemdescVar.tdesc.lptdesc = ptrtd;
  414.     ptrtd->vt = sym->GetDataType();
  415.   } else if (sym->IsByRef()) {
  416.     vd->elemdescVar.tdesc.vt = VT_PTR;
  417.     vd->elemdescVar.tdesc.lptdesc = ptrtd;
  418.     ptrtd->vt = sym->GetDataType();
  419.   } else {
  420.     vd->elemdescVar.tdesc.vt = sym->GetDataType();
  421.   }
  422.   *retDesc = vd;
  423.   return HR_NOERROR;
  424. }
  425.  
  426. void _IFUNC
  427. TServedObject::ReleaseVarDesc(VARDESC far* pvardesc)
  428. {
  429.   delete pvardesc;
  430.   return;
  431. }
  432.  
  433. HRESULT _IFUNC
  434. TServedObject::GetNames(MEMBERID memid, BSTR far* rgbstrNames,
  435.                         unsigned int cMaxNames, unsigned int far* pcNames)
  436. {
  437.   ObjectPtr noObj = 0;
  438.   TAutoSymbol* sym = Class->FindId(memid, noObj);
  439.   if (!sym)
  440.     return HR_DISP_MEMBERNOTFOUND;
  441.   int nameCount = Class->GetArgCount(*sym) + 1;
  442.   if (nameCount > cMaxNames)
  443.     nameCount = cMaxNames;
  444.   for (int index = 0; index < nameCount; index++, sym++)
  445.     rgbstrNames[index] = NS_CLASSLIB::SysAllocString(sym->Name.Translate(ReqLang));
  446.   *pcNames = nameCount;
  447.   return HR_NOERROR;
  448. }
  449.  
  450. HRESULT _IFUNC
  451. TServedObject::GetIDsOfNames(OLECHAR far* far* names, uint cNames,
  452.                              MEMBERID far* retIds)
  453. {
  454.   HRESULT retval = HR_NOERROR;
  455.   TAutoSymbol* symbol;
  456.   for (int i = 0; i < cNames; i++) {
  457.     retIds[i] = -1;
  458.     if (i == 0) {
  459.       symbol = Class->Lookup(OleStr(names[0]), ReqLang, asAnyCommand, retIds[0]);
  460.       if (!symbol)
  461.         retval = HR_DISP_UNKNOWNNAME;
  462.     }
  463.     else if (symbol) {
  464.       if (!Class->LookupArg(OleStr(names[i]), ReqLang, symbol, retIds[i]))
  465.         retval = HR_DISP_UNKNOWNNAME;
  466.     }
  467.   }
  468.   return retval;
  469. }
  470.  
  471. HRESULT _IFUNC
  472. TServedObject::Invoke(void far* pvInstance, MEMBERID memid,
  473.                       unsigned short wFlags, DISPPARAMS far *dispparams,
  474.                       VARIANT far *varResult, EXCEPINFO far *exceptinfo,
  475.                       unsigned int far *retArgErr)
  476. {
  477.   if (Object)   // cannot invoke if active object obtained from IDispatch ifc
  478.     return HR_TYPE_INVALIDSTATE;
  479.   Object = (void*)pvInstance; // going on faith that caller has valid instance
  480.   RootObject = NS_OCF::MostDerived(Object, Class->GetTypeInfo());
  481.   HRESULT stat = Invoke(memid, IID_NULL, ReqLang, wFlags, dispparams,
  482.                         varResult, exceptinfo, retArgErr);
  483.   Object = 0;
  484.   RootObject = 0;
  485.   return stat;
  486. }
  487.  
  488. HRESULT _IFUNC
  489. TServedObject::GetDocumentation(MEMBERID memid,
  490.                                 BSTR far* retName, BSTR far* retDoc,
  491.                                 ulong far* retHelpContext,
  492.                                 BSTR far* retHelpFile)
  493. {
  494.   TAutoSymbol* sym;
  495.   if (memid == -1) {       // request info on type library itself
  496.     sym = Class->GetClassSymbol();
  497.   } else {
  498.     ObjectPtr noObj = 0;
  499.     if ((sym = Class->FindId(memid, noObj)) == 0)
  500.       return HR_DISP_MEMBERNOTFOUND;
  501.   }
  502.   if (retName)
  503.     *retName = NS_CLASSLIB::SysAllocString(sym->Name.Translate(ReqLang));
  504.   if (retDoc)
  505.     *retDoc  = NS_CLASSLIB::SysAllocString(sym->Doc.Translate(ReqLang));
  506.   if (retHelpContext)
  507.     *retHelpContext = sym->HelpId;
  508.   if (retHelpFile)
  509.     *retHelpFile = NS_CLASSLIB::SysAllocString(
  510.       Creator.AppDesc.GetHelpFile(ReqLang));
  511.   return HR_NOERROR;
  512. }
  513.  
  514. HRESULT _IFUNC
  515. TServedObject::GetFuncDocFromIndex(unsigned index,
  516.                                    BSTR far* retName, BSTR far* retDoc,
  517.                                    ulong far* retHelpContext,
  518.                                    BSTR far* retHelpFile)
  519. {
  520.   MEMBERID cmdId = 0;
  521.   TAutoSymbol* sym = Class->FindFunction(index, cmdId);
  522.   if (!sym)
  523.     return HR_INVALIDARG;
  524.   return GetDocFromSym(sym, retName, retDoc,retHelpContext, retHelpFile);
  525. }
  526.  
  527. HRESULT _IFUNC
  528. TServedObject::GetVarDocFromIndex(unsigned index,
  529.                                   BSTR far* retName, BSTR far* retDoc,
  530.                                   ulong far* retHelpContext,
  531.                                   BSTR far* retHelpFile)
  532. {
  533.   MEMBERID cmdId = 0;
  534.   TAutoSymbol* sym = Class->FindVariable(index, cmdId);
  535.   if (!sym)
  536.     return HR_INVALIDARG;
  537.   return GetDocFromSym(sym, retName, retDoc,retHelpContext, retHelpFile);
  538. }
  539.  
  540. HRESULT _IFUNC
  541. TServedObject::GetDocFromSym(TAutoSymbol* sym,
  542.                              BSTR far* retName, BSTR far* retDoc,
  543.                              ulong far* retHelpContext,
  544.                              BSTR far* retHelpFile)
  545. {
  546.   if (retName)
  547.     *retName = NS_CLASSLIB::SysAllocString(sym->Name.Translate(ReqLang));
  548.   if (retDoc)
  549.     *retDoc  = NS_CLASSLIB::SysAllocString(sym->Doc.Translate(ReqLang));
  550.   if (retHelpContext)
  551.     *retHelpContext = sym->HelpId;
  552.   if (retHelpFile)
  553.     *retHelpFile = NS_CLASSLIB::SysAllocString(Creator.AppDesc.GetHelpFile(ReqLang));
  554.   return HR_NOERROR;
  555. }
  556.  
  557. HRESULT _IFUNC
  558. TServedObject::CreateInstance(IUnknown* /*punkOuter*/, const IID far& /*riid*/,
  559.                               void far* far* /*ppvObj*/)
  560. {
  561.   return HR_TYPE_WRONGTYPEKIND;
  562. }
  563.  
  564. HRESULT _IFUNC
  565. TServedObject::GetContainingTypeLib(ITypeLib* far* retLib,
  566.                                                 unsigned int far* retIndex)
  567. {
  568.   *retLib = Creator.AppDesc.GetTypeLibrary();
  569.   if (retIndex)
  570.     *retIndex = Creator.AppDesc.GetClassIndex(Class);
  571.   return HR_NOERROR;  // is it really possible to fail?
  572. }
  573.  
  574. HRESULT _IFUNC
  575. TServedObject::GetRefTypeInfo(HREFTYPE hreftype, ITypeInfo* far* retInfo)
  576. {
  577.   TAutoClass* cls = (TAutoClass*)hreftype;
  578.   if (Creator.AppDesc.GetClassIndex(cls) == -1)  // validate pointer to avoid crash
  579.     return HR_TYPE_WRONGTYPEKIND;
  580.   *retInfo = Creator.AppDesc.CreateITypeInfo(*cls);
  581.   return HR_NOERROR;
  582. }
  583.  
  584. // The following methods of ITypeInfo are not relevant for Dispatch interfaces
  585.  
  586. HRESULT _IFUNC
  587. TServedObject::GetTypeComp(ITypeComp* far* /*pptcomp*/)
  588. {
  589.   return HR_TYPE_LIBNOTREGISTERED;
  590. }
  591.  
  592. HRESULT _IFUNC
  593. TServedObject::GetMops(MEMBERID /*memid*/, BSTR far*)
  594. {
  595.   return HR_TYPE_WRONGTYPEKIND;
  596. }
  597.  
  598. HRESULT _IFUNC
  599. TServedObject::GetImplTypeFlags(unsigned int /*index*/, int far*)
  600. {
  601.   return HR_TYPE_WRONGTYPEKIND;
  602. }
  603.  
  604. HRESULT _IFUNC
  605. TServedObject::GetRefTypeOfImplType(unsigned int /*index*/,
  606.                                     HREFTYPE far* /*phreftype*/)
  607. {
  608.   return HR_TYPE_WRONGTYPEKIND;
  609. }
  610.  
  611. HRESULT _IFUNC
  612. TServedObject::GetDllEntry(MEMBERID /*memid*/, INVOKEKIND /*invkind*/,
  613.                            BSTR far* /*pbstrDllName*/, BSTR far* /*pbstrName*/,
  614.                            unsigned short far* /*pwOrdinal*/)
  615. {
  616.   return HR_TYPE_WRONGTYPEKIND;
  617. }
  618.  
  619. HRESULT _IFUNC
  620. TServedObject::AddressOfMember(MEMBERID /*memid*/, INVOKEKIND /*invkind*/,
  621.                                void far* far* /*ppv*/)
  622. {
  623.   return HR_TYPE_WRONGTYPEKIND;
  624. }
  625.